package com.slwu.configure;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 序列
 * </p>
 *
 * @author wushaolin
 * @since 2022-10-09
 */
@Component
public class Sequence {

    @Resource
    private RedisTemplate<String, Integer> redisTemplate;


    /**
     * 获取序列 next 值
     * @param name 序列名称
     * @param length 结果长度
     * @param expireSecond 过期时间，秒
     * @return 序列 next 值
     */
    public String getNextValue(String name, int length, Long expireSecond) {
        long id = this.getSequenceId(name, expireSecond);
        return this.getString(id, length);
    }

    private long getSequenceId(String name, Long expireSecond) {
        String TOKEN_PRE = "Sequence";
        String key = RedisKey.redisKeyGenerator(TOKEN_PRE, name);
        return this.incr(key, expireSecond);
    }

    private long incr(String key, Long expireSecond) {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        long increment = entityIdCounter.getAndIncrement();
        if (increment == 0) {
            if (expireSecond != null && expireSecond > 0L) {
                entityIdCounter.expire(expireSecond, TimeUnit.SECONDS);
            }
            increment = entityIdCounter.getAndIncrement();
        }
        return increment;
    }

    private String getString(long id, int length) {
        String idStr = String.valueOf(id);

        // 长度不够时，自动补长度
        if (idStr.length() > length) {
            length = idStr.length();
        }
        StringBuilder buffer = new StringBuilder(idStr);
        for (int i = idStr.length(); i < length; i++) {
            buffer.insert(0, "0");
        }
        return buffer.toString();
    }
}
